package nia.chapter2.echoclient;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.ByteProcessor;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

/**
 * 代码清单 2-4 客户端的主类
 *
 * @author <a href="mailto:norman.maurer@gmail.com">Norman Maurer</a>
 */
public class EchoClient {
    private final String host;
    private final int port;

    public EchoClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void start()
        throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //创建 Bootstrap
            Bootstrap b = new Bootstrap();
            //指定 EventLoopGroup 以处理客户端事件；需要适用于 NIO 的实现
            b.group(group)
                //适用于 NIO 传输的Channel 类型
                .channel(NioSocketChannel.class)
                //设置服务器的InetSocketAddress
                .remoteAddress(new InetSocketAddress(host, port))
                //在创建Channel时，向 ChannelPipeline中添加一个 EchoClientHandler实例
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch)
                        throws Exception {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(new MyChannelOutboundHandler());
                        ch.pipeline().addLast(new EchoClientHandler());

                    }
                });
            //连接到远程节点，阻塞等待直到连接完成
            ChannelFuture f = b.connect().sync();
            test1(f);
            //test2(f);
            //test3(f);
            //test4(f);
            //阻塞，直到Channel 关闭
            f.channel().closeFuture().sync();
        } finally {
            //关闭线程池并且释放所有的资源
            //group.shutdownGracefully().sync();
        }
    }
    //测试方法
    private void test1(ChannelFuture f){
        Channel channel = f.channel();
        String s = channel.id().asLongText();
        String id = "80fa5bfffe02030b-00001c1c-00000000-d088b5ea494679ed-633053f0";
        boolean b = s.equals(id);
        Charset utf8 = Charset.forName("utf-8");
        ByteBuf byteBuf = Unpooled.copiedBuffer("ni\rhao\r", utf8);
        int i = byteBuf.forEachByte(ByteProcessor.FIND_CR);
        ByteBuf slice = byteBuf.slice(0, 5);
        slice.setByte(0,(byte)'l');
        assert byteBuf.getByte(0)==slice.getByte(0);
        ByteBuf copy = byteBuf.copy(0, 5);
        copy.setByte(0,'1');
        assert copy.getByte(0)!=byteBuf.getByte(0);


    }

    private void test2(ChannelFuture f){
        Channel channel = f.channel();
        Charset utf8 = Charset.forName("utf-8");
        ByteBuf byteBuf = Unpooled.copiedBuffer("ni\rhao\r", utf8);
        //类似于List集合，默认分配capacity大小
        int capacity = byteBuf.capacity();
        int maxCapacity = byteBuf.maxCapacity();
        //如果byteBuf以字节数组支撑
        boolean b = byteBuf.hasArray();
        if(b){
            byte[] array = byteBuf.array();
            System.out.println();
        }
        //可读字节数是从0到写的位置
        int readerIndex1 = byteBuf.readerIndex();
        int readableBytes = byteBuf.readableBytes();
        //可写字节数是从写的位置到capacity
        int writerIndex1 = byteBuf.writerIndex();
        int wirtableNum = byteBuf.writableBytes();
        byteBuf.writeInt(12);
        int readerIndex = byteBuf.readerIndex();
        int writerIndex = byteBuf.writerIndex();
        int readableBytes1 = byteBuf.readableBytes();
        int wirtableNum1 = byteBuf.writableBytes();





    }

    //测试方法
    private void test3(ChannelFuture f){
        Channel channel = f.channel();
        Charset utf8 = Charset.forName("utf-8");
        PooledByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;
        //堆内存
        ByteBuf heapBuffer = allocator.heapBuffer();
        //返回基于堆或者直接内存存储的bytebuf
        ByteBuf buffer = allocator.buffer();
        ByteBuf buffer1 = allocator.buffer(42);
        ByteBuf buffer2 = allocator.buffer(42,1024);
        //基于直接内存
        ByteBuf directBuffer = allocator.directBuffer();
        //服务缓冲区
        CompositeByteBuf compositeByteBuf = allocator.compositeBuffer();
        ByteBufAllocator alloc = channel.alloc();
        //ctx.alloc();
        //返回一个复制了给定数据的 ByteBuf
        ByteBuf byteBuf = Unpooled.copiedBuffer("nihao", utf8);
        //返回一个包装了给定数据的 ByteBuf
        ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(buffer);
        //以十六进制打印
        String s = ByteBufUtil.hexDump(buffer);
        //判断是否相等
        boolean equals = ByteBufUtil.equals(byteBuf, buffer);


    }
    private void test4(ChannelFuture f){
        Channel channel = f.channel();
        ByteBufAllocator alloc = channel.alloc();
        ByteBuf byteBuf = alloc.directBuffer();
        assert byteBuf.refCnt()==1;
        boolean release = byteBuf.release();
    }
}

